#include "robotplaygroundJoystick.h"
#include <string.h>
#pragma comment(lib, "winmm.lib")
#include <windows.h>
#include <mmsystem.h>
#include <iostream>
#include <conio.h>

using namespace std;

JNIEXPORT jint JNICALL Java_net_zarubsys_robotplayground_joystick_JoystickNativeAccessor_openJoystick (JNIEnv * env, jobject obj, jstring name) {
	string devName = env->GetStringUTFChars(name, NULL);
	int id = atoi(devName.c_str());
	JOYCAPS joyCaps;
	long value = joyGetDevCaps(id, &joyCaps, sizeof(joyCaps));
	if (value != 0) return -1;
	return id;
}

JNIEXPORT void JNICALL Java_net_zarubsys_robotplayground_joystick_JoystickNativeAccessor_closeJoystick(JNIEnv * env, jobject obj, jint id) {
	/* Not necessary on Windows */
	return;
}

JNIEXPORT jstring JNICALL Java_net_zarubsys_robotplayground_joystick_JoystickNativeAccessor_readSignature(JNIEnv * env, jobject obj, jint id) {
	JOYCAPS joyCaps;
	long value = joyGetDevCaps(id, &joyCaps, sizeof(joyCaps));
	if (value != 0) return NULL;
	#ifdef _UNICODE
	 return env->NewStringUTF("Joystick");
	#else
	 char * name = (char *) joyCaps.szPname;
	 	return env->NewStringUTF(name);
	#endif
	

}

JNIEXPORT void JNICALL Java_net_zarubsys_robotplayground_joystick_JoystickNativeAccessor_readEvents(JNIEnv * env, jobject obj, jint id, jobject callback) {
	jclass callbackClass = env->GetObjectClass(callback);
	jmethodID doCloseMethod = env->GetMethodID(callbackClass, "doClose", "()Z");
	if (doCloseMethod == NULL) {
		printf("Cannot find signature of doClose method!");
		return; /* method not found */
	}
	jmethodID callbackMethod = env->GetMethodID(callbackClass, "callback", "(III)V");
	if (callbackMethod == NULL) {
		printf("Cannot find signature of callback method!");
		return; /* method not found */
	}

	while(1) {
		jboolean doClose = env->CallBooleanMethod(callback, doCloseMethod);
		if (doClose) return;

		
		JOYINFO jiInfo;
		joyGetPos(id, &jiInfo);
		// send buttons
		env->CallVoidMethod(callback, callbackMethod, 1, 0, jiInfo.wButtons & JOY_BUTTON1);
		env->CallVoidMethod(callback, callbackMethod, 1, 1, jiInfo.wButtons & JOY_BUTTON2);
		env->CallVoidMethod(callback, callbackMethod, 1, 2, jiInfo.wButtons & JOY_BUTTON3);
		env->CallVoidMethod(callback, callbackMethod, 1, 3, jiInfo.wButtons & JOY_BUTTON4);

		// send axis
		env->CallVoidMethod(callback, callbackMethod, 2, 0, jiInfo.wXpos - 32767);
		env->CallVoidMethod(callback, callbackMethod, 2, 1, jiInfo.wYpos - 32767);
		Sleep(100);
	}
	return;
}
